﻿using System;
using System.Collections.Concurrent;
using System.Linq;
using System.Reflection;
using NiuX.Utils.DependencyInjection.Attributes;

namespace NiuX.Utils.DependencyInjection;

public class IocFactory
{
    private readonly ConcurrentDictionary<string, object> _container = new ConcurrentDictionary<string, object>();


    private readonly ConcurrentDictionary<string, Type> _typeContainer = new ConcurrentDictionary<string, Type>();


    public void Load(Assembly assembly)
    {
        foreach (var type in assembly.GetTypes().Where(x => x.GetCustomAttribute<InjectionAttribute>() != null))
        {
            _typeContainer.TryAdd(type.FullName!, type);
        }
    }

    public object Get(string fullName)
    {
        if (_container.TryGetValue(fullName, out var obj))
        {
            return obj;
        }

        if (!_typeContainer.TryGetValue(fullName, out var type))
        {
            throw new Exception("对象尚未注册");
        }

        var instance = Activator.CreateInstance(type);

        foreach (var property in type.GetProperties())
        {
            var injectionProperty = property.GetCustomAttribute<InjectionAttribute>();

            if (injectionProperty == null)
            {
                continue;
            }

            var propertyInstance = Get(property.PropertyType.FullName);
            property.SetValue(instance, propertyInstance);
        }

        _container.TryAdd(type.FullName!, instance);
        return instance;
    }

    public T Get<T>(string fullName) => (T)Get(fullName);

}